import json
import logging
import math
import re
import urllib
from datetime import datetime
import hashlib
from urllib.parse import urlencode, unquote

import jsonpath
import requests
from django.http import JsonResponse
from django.views import View
from lapi_app.models.environment_model.environment import Environment
from lapi_app.models.testcase_model.testcase import Variable_local, Testcase, Asserts, case_result

logger = logging.getLogger('django')


class Send_request(View):

    def post(self, request, *args, **kwargs):
        global extract_dict, res, extract_result, result, req_url, params, headers, payload, data, t_id
        try:
            body_data = request.body
            if not body_data:
                return JsonResponse({
                    "code": 100,
                    "message": "参数异常"
                })
            data = json.loads(body_data)
            t_id = data["testcase_id"]
            t_url = data["url"]
            t_type = data["body_type"]
            t_body = data["body"]
            t_method = data["method"]
            t_params = data["params"]
            t_headers = data["headers"]
            t_assert = data["assert"]
            api_type = data["api_type"]
            t_env_id = data["environment_id"]
            t_extract = data["variable_extract"]
            if t_id != '' or t_id is not None:
                cases = Testcase.objects.filter(id=t_id)
                cases.update(t_url=t_url, t_extract=t_extract, t_type=t_type, t_body=t_body, t_params=t_params,
                             t_method=t_method, t_header=t_headers, t_environment_id=t_env_id, api_type=api_type,
                             update_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

            # 请求的域名
            req_api = Environment.objects.get(id=data["environment_id"])
            # 请求地址
            if re.match(r'^https?:/{2}\w.+$', t_url):
                req_url = t_url
            else:
                req_url = req_api.e_address + data["url"]

            # url处理
            if "${" in req_url and "}" in req_url:
                key = re.findall(r"\${(.+?)}", req_url)
                for a in range(len(key)):
                    v_key = "${" + key[a] + "}"
                    value_variable = Variable_local.objects.filter(local_name=str(v_key))
                    if value_variable.count() > 0:
                        variable = value_variable[0].local_result
                        req_url = req_url.replace(v_key, variable)
                    else:
                        return JsonResponse({
                            "code": 101,
                            "message": str(v_key) + "变量数据库未找到"
                        })
            logger.info("请求url=" + req_url)

            # body处理
            if data["body"] == '' or data["body"] == {}:
                payload = data["body"]
            else:
                try:
                    body = data["body"]
                    # 判断变量是否存在
                    if "${" in json.dumps(body) and "}" in json.dumps(body):
                        key = re.findall(r"\${(.+?)}", json.dumps(body))
                        for b in range(len(key)):
                            b_key = "${" + key[b] + "}"
                            value_variable = Variable_local.objects.filter(local_name=str(b_key))
                            if value_variable.count() > 0:
                                variable = value_variable[0].local_result
                                body = json.dumps(body).replace(b_key, variable)
                                body = json.loads(body)
                            else:
                                return JsonResponse({
                                    "code": 101,
                                    "message": str(b_key) + "变量数据库未找到"
                                })
                    payload = body
                except Exception as e:
                    return JsonResponse({
                        "code": 101,
                        "message": "body参数类型错误",
                        "system_log": e
                    })

            # headers处理
            head = data["headers"]
            if not head:
                headers = {}
            else:
                try:
                    if "${" in json.dumps(head) and "}" in json.dumps(head):
                        key = re.findall(r"\${(.+?)}", json.dumps(head))
                        for b in range(len(key)):
                            h_key = "${" + key[b] + "}"
                            value_variable = Variable_local.objects.filter(local_name=str(h_key))
                            if value_variable.count() > 0:
                                variable = value_variable[0].local_result
                                head = json.dumps(head).replace(h_key, variable)
                            else:
                                return JsonResponse({
                                    "code": 101,
                                    "message": str(h_key) + "变量数据库未找到"
                                })
                    headers = head
                except Exception as e:
                    return JsonResponse({
                        "code": 101,
                        "message": "header参数类型错误",
                        "system_log": e
                    })
            if api_type == 1:
                # 普通接口
                pass

            # 请求方法：1：get， 2：post， 3：put， 4：delete
            # 参数类型：1:form-data， 2:Json， 3:x-www-form-urlencoded， 4:None
            # method处理
            # params处理
            p = data["params"]
            params = {}
            if not p:
                for item in p:
                    params[item["key"]] = item["value"]
            logger.info("请求参数 =" + json.dumps(params))

            method = str(data['method'])
            body_type = str(data['body_type'])
            # res = send_requests(method, body_type, req_url, payload, headers)
            # Get
            if method == "1":
                if body_type == "1":
                    res = requests.get(req_url, params=params, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "2":
                    res = requests.get(req_url, json=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "3":
                    res = requests.get(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "4":
                    res = requests.get(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)

            # Post
            if method == "2":
                if body_type == "1":
                    res = requests.post(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "2":
                    res = requests.post(req_url, json=payload, headers=headers, params=params)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "3":
                    res = requests.post(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "4":
                    res = requests.post(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
            # Put
            if method == "3":
                if body_type == "1":
                    res = requests.put(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "2":
                    res = requests.put(req_url, json=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "3":
                    res = requests.put(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "4":
                    res = requests.post(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)

            # Delete
            if method == "4":
                if body_type == "1":
                    res = requests.delete(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "2":
                    res = requests.delete(req_url, json=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "3":
                    res = requests.delete(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)
                elif body_type == "4":
                    res = requests.delete(req_url, data=payload, headers=headers)
                    logger.info("响应结果 =" + res.text)

            assert_a = data["assert"]
            result = []
            if assert_a and res:
                assert_data = {item['assert_key']: item['assert_value'] for item in assert_a}
                for key, value in assert_data.items():
                    if str(value) == str(jsonpath.jsonpath(res.json(), key)[0]):
                        assert_status = {
                                    "status": True,
                                    "assert_key": key,
                                    "assert_value": str(value),
                                }
                    else:
                        assert_status = {
                            "status": False,
                            "assert_key": key,
                            "assert_value": str(value),
                        }
                    result.append(assert_status)
            logger.info(f"断言结果={result}")
            if result:
                for ats in result:
                    if Asserts.objects.filter(assert_testcase_id=t_id,
                                              assert_key=str(ats["assert_key"])).exists():
                        Asserts.objects.filter(assert_testcase_id=t_id, assert_key=str(ats["assert_key"])). \
                            update(assert_status=str(ats["status"]), assert_value=ats["assert_value"])
                    else:
                        Asserts.objects.create(assert_testcase_id=t_id, assert_key=str(ats["assert_key"]),
                                               assert_value=ats["assert_value"],
                                               assert_status=str(ats["status"]))
            elif not result:
                Asserts.objects.filter(assert_testcase_id=t_id).delete()

            # variable提取处理
            extract_result = []
            extract = data["variable_extract"]
            if extract is None or extract == "":
                extract_result = []
            else:
                for v in extract:
                    if v["variable_name"] == "" or v["variable_data"] == "":
                        extract_dict = {
                            "message": "无参数提取"
                        }
                        extract_result.append(extract_dict)
                    else:
                        # 提取变量
                        try:
                            res_result = json.loads(res.text)
                        except Exception as e:
                            logger.info(str(e))
                            pass
                        v_data = v["variable_data"].split(".")
                        try:
                            for a in v_data:
                                if "[" in a and "]" in a:
                                    variable_1 = a.split('[')[0]
                                    variable_2 = a.split('[')[1].split(']')[0]
                                    res_result = res_result[variable_1][variable_2]
                                else:
                                    res_result = res_result[a]
                            extract_dict = {
                                "variable_name": v["variable_name"],
                                "variable_data": v["variable_data"],
                                "variable_result": str(res_result),
                                "status": 1
                            }
                            extract_result.append(extract_dict)
                        except Exception as e:
                            extract_dict = {
                                "variable_name": v["variable_name"],
                                "variable_data": v["variable_data"],
                                "variable_result": "参数提取失败" + str(e),
                                "status": 0
                            }
                            extract_result.append(extract_dict)
                for e in extract_result:
                    if e["status"] == 1:
                        if Variable_local.objects.filter(local_name=e["variable_name"]).count() > 0:
                            Variable_local.objects.filter(local_name=e["variable_name"]). \
                                update(local_data=e["variable_data"], local_result=e["variable_result"])
                        elif Variable_local.objects.filter(local_name=e["variable_name"]).count() == 0:
                            Variable_local.objects.filter(local_name=e["variable_name"]). \
                                create(local_name=e["variable_name"], local_data=e["variable_data"],
                                       local_result=e["variable_result"],
                                       local_user_id=data["user_id"])
                logger.info("参数提取结果 =" + str(extract_result))
                logger.info("接口响应时间 =" + str(round(res.elapsed.total_seconds() * 1000, 2)) + 'ms')
            case_result.objects.create(url=req_url, params=params, header=headers, body=payload, status=res.status_code,
                                       assert_data=result, response=json.loads(res.text), user_id=data["user_id"],
                                       extract=extract_result, method=data['method'], case_id=t_id, response_time=str(round(res.elapsed.total_seconds() * 1000, 2)))
            return JsonResponse({
                "code": 200,
                "host": req_url,
                "params": params,
                "headers": headers,
                "body": payload,
                "status": res.status_code,
                "size": str(res.text.__sizeof__() + res.headers.__sizeof__()) + " B",
                "assert_data": result,
                "res_data": json.loads(res.text),
                "response_time": str(round(res.elapsed.total_seconds() * 1000, 2)) + ' ms',
                "variable": extract_result
            })
        except Exception as e:
            case_result.objects.create(url=req_url, params=params, header=headers, body=payload, status=res.status_code,
                                       assert_data=result, response=res.text, user_id=data["user_id"],
                                       extract=extract_result, method=data['method'], case_id=t_id, response_time=str(round(res.elapsed.total_seconds() * 1000, 2)))
            return JsonResponse({
                "code": 100,
                "message": "接口请求失败：" + str(e),
                "content": {
                    "status": res.status_code,
                    "response_time": str(round(res.elapsed.total_seconds() * 1000, 2)) + ' ms',
                    "size": str(res.text.__sizeof__() + res.headers.__sizeof__()) + " B",
                }
            })